//! 脚本执行器
//! 
//! 负责执行解析后的AST

use std::collections::HashMap;
use crate::ast::*;
use crate::context::ScriptContext;
use crate::error::{ExecutionError, Result};

/// 执行结果
#[derive(Debug, Clone)]
pub struct ExecutionResult {
    /// 返回值
    pub value: Value,
    /// 执行统计
    pub stats: ExecutionStats,
}

/// 执行统计
#[derive(Debug, Clone)]
pub struct ExecutionStats {
    /// 执行时间（毫秒）
    pub execution_time_ms: u64,
    /// 执行的语句数
    pub statements_executed: usize,
    /// 函数调用次数
    pub function_calls: usize,
    /// 内存使用（字节）
    pub memory_used_bytes: usize,
}

/// 脚本执行器
pub struct ScriptExecutor {
    /// 执行上下文
    context: ScriptContext,
}

impl ScriptExecutor {
    /// 创建新的执行器
    pub fn new(context: ScriptContext) -> Self {
        Self { context }
    }
    
    /// 执行程序
    pub async fn execute(&mut self, program: Program) -> Result<ExecutionResult> {
        let start_time = std::time::Instant::now();
        let mut stats = ExecutionStats {
            execution_time_ms: 0,
            statements_executed: 0,
            function_calls: 0,
            memory_used_bytes: 0,
        };
        
        let mut last_value = Value::Null;
        
        for statement in program.statements {
            match self.execute_statement(statement, &mut stats).await? {
                ControlFlow::Continue(value) => {
                    last_value = value;
                },
                ControlFlow::Return(value) => {
                    last_value = value;
                    break;
                },
                ControlFlow::Break => break,
                ControlFlow::ContinueLoop => continue,
            }
        }
        
        stats.execution_time_ms = start_time.elapsed().as_millis() as u64;
        
        Ok(ExecutionResult {
            value: last_value,
            stats,
        })
    }
    
    /// 执行语句
    fn execute_statement<'a>(
        &'a mut self,
        statement: Statement,
        stats: &'a mut ExecutionStats,
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<ControlFlow>> + 'a>> {
        Box::pin(async move {
        stats.statements_executed += 1;
        
        match statement {
            Statement::VarDecl { name, value } => {
                let val = self.evaluate_expression(value, stats).await?;
                self.context.set_variable(name, val)?;
                Ok(ControlFlow::Continue(Value::Null))
            },
            
            Statement::Assignment { name, value } => {
                let val = self.evaluate_expression(value, stats).await?;
                self.context.set_variable(name, val)?;
                Ok(ControlFlow::Continue(Value::Null))
            },
            
            Statement::Expression(expr) => {
                let val = self.evaluate_expression(expr, stats).await?;
                Ok(ControlFlow::Continue(val))
            },
            
            Statement::If { condition, then_block, else_block } => {
                let condition_value = self.evaluate_expression(condition, stats).await?;
                
                if condition_value.is_truthy() {
                    self.execute_block(then_block, stats).await
                } else if let Some(else_stmts) = else_block {
                    self.execute_block(else_stmts, stats).await
                } else {
                    Ok(ControlFlow::Continue(Value::Null))
                }
            },
            
            Statement::While { condition, body } => {
                let mut last_value = Value::Null;
                
                loop {
                    let condition_value = self.evaluate_expression(condition.clone(), stats).await?;
                    if !condition_value.is_truthy() {
                        break;
                    }
                    
                    match self.execute_block(body.clone(), stats).await? {
                        ControlFlow::Continue(value) => last_value = value,
                        ControlFlow::Return(value) => return Ok(ControlFlow::Return(value)),
                        ControlFlow::Break => break,
                        ControlFlow::ContinueLoop => continue,
                    }
                }
                
                Ok(ControlFlow::Continue(last_value))
            },
            
            Statement::Return { value } => {
                let return_value = if let Some(expr) = value {
                    self.evaluate_expression(expr, stats).await?
                } else {
                    Value::Null
                };
                Ok(ControlFlow::Return(return_value))
            },
            
            Statement::Break => Ok(ControlFlow::Break),
            
            Statement::Continue => Ok(ControlFlow::ContinueLoop),
            
            Statement::Block(statements) => {
                self.execute_block(statements, stats).await
            },
            
            _ => {
                Err(ExecutionError::runtime_error("不支持的语句类型").into())
            }
        }
        })
    }
    
    /// 执行语句块
    fn execute_block<'a>(
        &'a mut self,
        statements: Vec<Statement>,
        stats: &'a mut ExecutionStats,
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<ControlFlow>> + 'a>> {
        Box::pin(async move {
        let mut last_value = Value::Null;
        
        for statement in statements {
            match self.execute_statement(statement, stats).await? {
                ControlFlow::Continue(value) => last_value = value,
                ControlFlow::Return(value) => return Ok(ControlFlow::Return(value)),
                ControlFlow::Break => return Ok(ControlFlow::Break),
                ControlFlow::ContinueLoop => return Ok(ControlFlow::ContinueLoop),
            }
        }
        
        Ok(ControlFlow::Continue(last_value))
        })
    }
    
    /// 计算表达式
    fn evaluate_expression<'a>(
        &'a mut self,
        expression: Expression,
        stats: &'a mut ExecutionStats,
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Value>> + 'a>> {
        Box::pin(async move {
        match expression {
            Expression::Literal(value) => Ok(value),
            
            Expression::Variable(name) => {
                self.context.get_variable_value(&name)
                    .ok_or_else(|| ExecutionError::undefined_variable(name).into())
            },
            
            Expression::BinaryOp { left, operator, right } => {
                let left_val = self.evaluate_expression(*left, stats).await?;
                let right_val = self.evaluate_expression(*right, stats).await?;
                self.apply_binary_operator(operator, left_val, right_val)
            },
            
            Expression::UnaryOp { operator, operand } => {
                let operand_val = self.evaluate_expression(*operand, stats).await?;
                self.apply_unary_operator(operator, operand_val)
            },
            
            Expression::FunctionCall { name, args } => {
                stats.function_calls += 1;
                self.call_function(name, args, stats).await
            },
            
            _ => {
                Err(ExecutionError::runtime_error("不支持的表达式类型").into())
            }
        }
        })
    }
    
    /// 应用二元操作符
    fn apply_binary_operator(
        &self,
        operator: BinaryOperator,
        left: Value,
        right: Value,
    ) -> Result<Value> {
        match (operator, left, right) {
            // 算术操作
            (BinaryOperator::Add, Value::Integer(a), Value::Integer(b)) => {
                Ok(Value::Integer(a + b))
            },
            (BinaryOperator::Add, Value::Float(a), Value::Float(b)) => {
                Ok(Value::Float(a + b))
            },
            (BinaryOperator::Add, Value::String(a), Value::String(b)) => {
                Ok(Value::String(a + &b))
            },
            
            (BinaryOperator::Subtract, Value::Integer(a), Value::Integer(b)) => {
                Ok(Value::Integer(a - b))
            },
            (BinaryOperator::Subtract, Value::Float(a), Value::Float(b)) => {
                Ok(Value::Float(a - b))
            },
            
            (BinaryOperator::Multiply, Value::Integer(a), Value::Integer(b)) => {
                Ok(Value::Integer(a * b))
            },
            (BinaryOperator::Multiply, Value::Float(a), Value::Float(b)) => {
                Ok(Value::Float(a * b))
            },
            
            (BinaryOperator::Divide, Value::Integer(a), Value::Integer(b)) => {
                if b == 0 {
                    Err(ExecutionError::DivisionByZero.into())
                } else {
                    Ok(Value::Integer(a / b))
                }
            },
            (BinaryOperator::Divide, Value::Float(a), Value::Float(b)) => {
                if b == 0.0 {
                    Err(ExecutionError::DivisionByZero.into())
                } else {
                    Ok(Value::Float(a / b))
                }
            },
            
            // 比较操作
            (BinaryOperator::Equal, a, b) => {
                Ok(Value::Boolean(self.values_equal(&a, &b)))
            },
            (BinaryOperator::NotEqual, a, b) => {
                Ok(Value::Boolean(!self.values_equal(&a, &b)))
            },
            
            (BinaryOperator::Less, Value::Integer(a), Value::Integer(b)) => {
                Ok(Value::Boolean(a < b))
            },
            (BinaryOperator::Less, Value::Float(a), Value::Float(b)) => {
                Ok(Value::Boolean(a < b))
            },
            
            (BinaryOperator::Greater, Value::Integer(a), Value::Integer(b)) => {
                Ok(Value::Boolean(a > b))
            },
            (BinaryOperator::Greater, Value::Float(a), Value::Float(b)) => {
                Ok(Value::Boolean(a > b))
            },
            
            // 逻辑操作
            (BinaryOperator::And, a, b) => {
                Ok(Value::Boolean(a.is_truthy() && b.is_truthy()))
            },
            (BinaryOperator::Or, a, b) => {
                Ok(Value::Boolean(a.is_truthy() || b.is_truthy()))
            },
            
            _ => Err(ExecutionError::type_error("不支持的操作符组合").into()),
        }
    }
    
    /// 应用一元操作符
    fn apply_unary_operator(&self, operator: UnaryOperator, operand: Value) -> Result<Value> {
        match (operator, operand) {
            (UnaryOperator::Minus, Value::Integer(n)) => Ok(Value::Integer(-n)),
            (UnaryOperator::Minus, Value::Float(f)) => Ok(Value::Float(-f)),
            (UnaryOperator::Plus, Value::Integer(n)) => Ok(Value::Integer(n)),
            (UnaryOperator::Plus, Value::Float(f)) => Ok(Value::Float(f)),
            (UnaryOperator::Not, value) => Ok(Value::Boolean(!value.is_truthy())),
            _ => Err(ExecutionError::type_error("不支持的一元操作符").into()),
        }
    }
    
    /// 调用函数
    async fn call_function(
        &mut self,
        name: String,
        args: Vec<Expression>,
        stats: &mut ExecutionStats,
    ) -> Result<Value> {
        // 计算参数值
        let mut arg_values = Vec::new();
        for arg in args {
            let value = self.evaluate_expression(arg, stats).await?;
            arg_values.push(value);
        }
        
        // 调用内置函数
        self.call_builtin_function(&name, arg_values)
    }
    
    /// 调用内置函数
    fn call_builtin_function(&self, name: &str, args: Vec<Value>) -> Result<Value> {
        match name {
            "print" => {
                if let Some(arg) = args.first() {
                    println!("{}", arg.to_string());
                }
                Ok(Value::Null)
            },
            
            "len" => {
                if let Some(Value::String(s)) = args.first() {
                    Ok(Value::Integer(s.len() as i64))
                } else if let Some(Value::Array(arr)) = args.first() {
                    Ok(Value::Integer(arr.len() as i64))
                } else {
                    Err(ExecutionError::argument_error("len函数需要字符串或数组参数").into())
                }
            },
            
            "to_string" => {
                if let Some(arg) = args.first() {
                    Ok(Value::String(arg.to_string()))
                } else {
                    Err(ExecutionError::argument_error("to_string函数需要一个参数").into())
                }
            },
            
            _ => Err(ExecutionError::undefined_function(name).into()),
        }
    }
    
    /// 比较两个值是否相等
    fn values_equal(&self, a: &Value, b: &Value) -> bool {
        match (a, b) {
            (Value::Null, Value::Null) => true,
            (Value::Boolean(a), Value::Boolean(b)) => a == b,
            (Value::Integer(a), Value::Integer(b)) => a == b,
            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
            (Value::String(a), Value::String(b)) => a == b,
            _ => false,
        }
    }
}

/// 控制流类型
#[derive(Debug, Clone)]
enum ControlFlow {
    Continue(Value),
    Return(Value),
    Break,
    ContinueLoop,
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::parser::ScriptParser;
    
    #[tokio::test]
    async fn test_execute_simple_expression() {
        let mut parser = ScriptParser::new();
        let program = parser.parse("var x = 42;").unwrap();
        
        let context = ScriptContext::new();
        let mut executor = ScriptExecutor::new(context);
        
        let result = executor.execute(program).await.unwrap();
        assert!(matches!(result.value, Value::Null));
        assert_eq!(result.stats.statements_executed, 1);
    }
    
    #[tokio::test]
    async fn test_execute_arithmetic() {
        let mut parser = ScriptParser::new();
        let program = parser.parse("var result = 1 + 2 * 3;").unwrap();
        
        let context = ScriptContext::new();
        let mut executor = ScriptExecutor::new(context);
        
        let result = executor.execute(program).await.unwrap();
        
        // 检查变量是否正确设置
        let var_value = executor.context.get_variable_value("result").unwrap();
        assert!(matches!(var_value, Value::Integer(7)));
    }
    
    #[tokio::test]
    async fn test_execute_function_call() {
        let mut parser = ScriptParser::new();
        let program = parser.parse(r#"print("Hello, World!");"#).unwrap();
        
        let context = ScriptContext::new();
        let mut executor = ScriptExecutor::new(context);
        
        let result = executor.execute(program).await.unwrap();
        assert_eq!(result.stats.function_calls, 1);
    }
}
